/**
 * java多线程模式
 * @author andy.rong
 */
package com.myjavalab.thread;

import java.util.LinkedList;
import java.util.Random;

public class GuardedSuspension {

	public static void main(String[] args) {
		RequestQueue queue = new RequestQueue();
		new ClientThread(queue, "Alice", 3472818L).start();
		new ServerThread(queue, "Bobby", 8372637L).start();
	}
}

class Request{
	private final String name;
	
	public Request(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
	
	public String toString() {
		return "[ Request " + name + " ]";
	}
}

class RequestQueue{
	private final LinkedList<Request> queue = new LinkedList<Request>();
	public synchronized Request getRequest() {
		System.out.println(Thread.currentThread().getName() + " is coming" + queue.size());		
		while(queue.size() <= 0) {
			try{
				System.out.println(Thread.currentThread().getName() + " is waiting");
				wait();
				System.out.println(Thread.currentThread().getName() + " after waiting");
				
			}catch (Exception e) {
				
			}
		}
		return queue.removeFirst();
	}
	
	public synchronized void putRequest(Request request) {
		queue.addLast(request);
		notifyAll();
		System.out.println(Thread.currentThread().getName() + " is notifing");
		
	}
}

class ClientThread extends Thread {
	private Random random;
	private RequestQueue requestQueue;
	
	public ClientThread(RequestQueue requestQueue, String name, long seed){
		super(name);
		this.requestQueue = requestQueue;
		this.random = new Random(seed);
	}
	
	public void run() {
		for(int i = 0; i < 10000; i++) {
			Request request = new Request("No." + i);
			System.out.println(Thread.currentThread().getName() + " requests " + request);
			requestQueue.putRequest(request);
			try{
				Thread.sleep(random.nextInt(1000));
			}catch(InterruptedException e){
				
			}
		}
	}
}

class ServerThread extends Thread {
	private Random random;
	private RequestQueue requestQueue;
	
	public ServerThread(RequestQueue requestQueue, String name, long seed){
		super(name);
		this.requestQueue = requestQueue;
		this.random = new Random(seed);
	}
	
	public void run() {

		for(int i = 0; i < 10000; i++) {
			Request request = requestQueue.getRequest();
			System.out.println(Thread.currentThread().getName() + " handles " + request);
			try{
				Thread.sleep(random.nextInt(1000));
			}catch(InterruptedException e){
				
			}
		}
	}
}